/*
 * CommonsIO.java
 * 
 * Copyright (C) 2010 no.good.at.coding
 * 
 * This file is part of the NoGoodCommons Library.
 * 
 * The NoGoodCommons Library is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package com.nogoodatcoding.commons;

import com.sun.syndication.feed.synd.SyndFeed;
import com.sun.syndication.io.FeedException;
import com.sun.syndication.io.SyndFeedOutput;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Properties;
import java.util.ResourceBundle;

import org.apache.log4j.Logger;

/**
 * Common IO related methods that can be used in a variety of projects
 * 
 * @author no.good.at.coding
 */
public class CommonsIO
{
    private static Logger log = Logger.getLogger(Commons.class);
    private static ResourceBundle bundle = ResourceBundle
            .getBundle("com.nogoodatcoding.commons.messages.Messages_CommonsIO");

    /**
     * 
     * Writes the given feed into a file at the given path
     * 
     * @param feedPath
     *            The path to the feed's XML
     * 
     * @param feed
     *            The feed to be written out to file
     * 
     * @throws java.io.IOException
     * 
     * @throws com.sun.syndication.io.FeedException
     * 
     */
    public static void writeFeed(String feedPath, SyndFeed feed) throws IOException, FeedException
    {
        SyndFeedOutput feedOutput = new SyndFeedOutput();

        feedOutput.output(feed, new File(feedPath));
    }

    /**
     * 
     * Loads the properties file
     * 
     * @param pathToProperties
     *            The location of the properties file
     * 
     * @return The loaded {@link Properties} object
     * 
     * @throws java.io.IOException
     * 
     */
    public static Properties loadProperties(String pathToProperties) throws IOException
    {
        FileInputStream inStream = new FileInputStream(pathToProperties);
        Properties properties = new Properties();
        properties.load(inStream);
        inStream.close();

        return properties;
    }

    /**
     * Convenience method for calling {@code storeProperties(Properties, String, String)} with {@code null} for comments
     * 
     * @param properties
     *            The {@code Properties} object to be written
     * 
     * @param pathToProperties
     *            The path and name of the properties file to be written
     * 
     * 
     * @throws java.io.IOException
     */
    public static void storeProperties(Properties properties, String pathToProperties) throws IOException
    {
        storeProperties(properties, pathToProperties, null);
    }

    /**
     * 
     * Stores the {@code Properties} object to disk with the path and name specified in {@code pathToProperties}
     * 
     * @param properties
     *            The {@code Properties} object to be written
     * 
     * @param pathToProperties
     *            The path and name of the properties file to be written
     * 
     * @param comments
     *            Comments to be stored with the properties.
     * 
     * @throws java.io.IOException
     */
    public static void storeProperties(Properties properties, String pathToProperties, String comments)
            throws IOException
    {
        FileOutputStream outStream = new FileOutputStream(pathToProperties);
        properties.store(outStream, comments);
        outStream.close();
    }

/**
     *
     * Replaces any invalid filename characters with the {@code String}
     * specified in {@code replaceInvalidCharactersWith}. Since Windows FAT
     * filenames are pretty much the most restrictive, it considers that as the
     * lowest common denominator. This means that {@code |\?*<":>+[]/} are
     * not allowed. Note that this is NOT meant for paths; only filenames.
     *
     * @param unsafeFilename The potentially unsafe filename
     *
     * @param replaceInvalidCharactersWith The {@code String} with which
     *                                     invalid characters are to be replaced
     *                                     . Defaults to _ (underscore) if null.
     *
     * @return The safe filename
     */
    public static String makeStringSafeForFilenames(String unsafeFilename, String replaceInvalidCharactersWith)
    {
        log.trace(String.format(bundle.getString("log.trace.filename.replace.arguments"), unsafeFilename,
                replaceInvalidCharactersWith));
        if (replaceInvalidCharactersWith == null)
            replaceInvalidCharactersWith = "_";
        return unsafeFilename.replaceAll("[|\\\\?*<\":>+\\[\\]/]", replaceInvalidCharactersWith);
    }

    /**
     * Extracts the extension from the given filename (giving a blank if there is none).
     * 
     * NOTE: This has not been written for RTL languages; not sure how the extensions are given on such systems.
     * 
     * @param filename
     *            The filename from which the extension is to be extracted
     * 
     * @return The extension for the given filename (excluding the '.'); an empty {@code String} if there is no extension present
     */
    public static String getFileExtension(String filename)
    {
        log.trace(String.format(bundle.getString("log.trace.filename"), filename));
        int indexOfDot = filename.lastIndexOf(".");
        log.trace(String.format(bundle.getString("log.trace.filename.extension.index"), indexOfDot));

        if (indexOfDot == -1)
        {
            log.trace(bundle.getString("log.trace.filename.extension.null"));
            return "";
        }

        log.trace(String.format(bundle.getString("log.trace.filename.extension"), filename.substring(indexOfDot + 1)));
        return filename.substring(indexOfDot + 1);
    }
}
